home *** CD-ROM | disk | FTP | other *** search
/ Amiga Plus 2002 #11 / Amiga Plus CD - 2002 - No. 11.iso / Tools / Development / reportplus / source / f10.c < prev    next >
C/C++ Source or Header  |  2002-10-27  |  72KB  |  1,950 lines

  1. #include <exec/types.h>
  2. #include <exec/memory.h>
  3. #include <intuition/intuition.h>
  4. #include <intuition/gadgetclass.h>
  5. #include <libraries/gadtools.h>
  6. #include <dos/dos.h>
  7. #include <dos/dostags.h>
  8. #include <dos/dosextens.h>
  9. #include <dos/exall.h>
  10. #include <dos/datetime.h>
  11. #include <graphics/gfx.h>
  12.  
  13. #include <clib/alib_protos.h>
  14. #include <clib/intuition_protos.h>
  15. #include <clib/graphics_protos.h>
  16. #include <clib/dos_protos.h>
  17. #include <clib/gadtools_protos.h>
  18. #include <clib/exec_protos.h>
  19.  
  20. #include <ctype.h>
  21. #include <stdlib.h>
  22. #include <string.h>
  23. #include "rp.h"
  24.  
  25. #define ALL_REACTION_CLASSES
  26. #include <reaction/reaction.h>
  27.  
  28. #define FILESMODE_BUILD   0
  29. #define FILESMODE_COMPARE 1
  30.  
  31. #define VERSIONLENGTH     40
  32.  
  33. MODULE void updatefiles(void);
  34. MODULE void stage1(void);
  35. MODULE void files_work(void);         // for stage1()
  36. MODULE void stage2(void);
  37. MODULE void dobuffer(ULONG whichpen); // for stage2()
  38. MODULE void stopping(STRPTR status);
  39. MODULE void files_updatelog(void);
  40. MODULE void updateghosting(void);
  41. MODULE void gadgetstate(ABOOL starting);
  42. MODULE void AddFilesNode(struct List* ListPtr, STRPTR pathname, STRPTR datetime, STRPTR version, STRPTR size);
  43. MODULE void FreeFilesNodes(struct List* ListPtr);
  44. MODULE void addslash(void);
  45.  
  46. IMPORT ABOOL                ram;
  47. IMPORT SBYTE                page;
  48. IMPORT TEXT                 IOBuffer[LONGESTFIELD + 1],
  49.                             aslresult[PATHNAMEFIELD + 1];
  50. IMPORT ULONG                increment;
  51. IMPORT struct Screen*       ScreenPtr;
  52. IMPORT struct ExAllData*    EADataPtr;
  53. IMPORT struct Menu*         MenuPtr;
  54. IMPORT Object*              WinObject[FUNCTIONS + 1];
  55. IMPORT struct Library      *ButtonBase,
  56.                            *CheckBoxBase,
  57.                            *ChooserBase,
  58.                            *IconBase,
  59.                            *LabelBase,
  60.                            *LayoutBase,
  61.                            *ListBrowserBase,
  62.                            *StringBase,
  63.                            *WindowBase;
  64. IMPORT struct TextAttr      Topaz8;
  65.  
  66. AGLOBAL struct Gadget*      files_gadgets[GIDS_10 + 1];
  67. AGLOBAL struct FilesStruct  files =
  68. {   TRUE, TRUE, TRUE, TRUE,
  69.     TRUE, TRUE, TRUE, TRUE,
  70.     0, FILESMODE_COMPARE,
  71.     "RAM:ReportPlus.log", "PROGDIR:ReportPlus.snapshot", "SYS:"
  72. };
  73.  
  74. MODULE BOOL                 outerghost       = FALSE,
  75.                             innerghost       = FALSE;
  76. MODULE struct List          DirList,         // list of PathnameNodes (internal use)
  77.                             FoundList,       // list of FilesNodes
  78.                             ResultList,      // listbrowser list
  79.                             EmptyResultList, // listbrowser list
  80.                             SnapshotList;    // list of FilesNodes (internal use)
  81. MODULE ULONG                filesfound,
  82.                             status           = STATUS_READY;
  83.  
  84. MODULE struct FilesNode
  85. {   struct Node Node;
  86.     ABOOL       matched;
  87.     TEXT        datetime[18 + 1],
  88.                 version[VERSIONLENGTH + 1],
  89.                 size[13 + 1],
  90.                 pathname[1];
  91. };
  92.  
  93. MODULE  BPTR           TheHandle             = NULL;
  94. MODULE  TEXT           activedir[PATHNAMEFIELD + 1],
  95.                        activefile[PATHNAMEFIELD + 1],
  96.                        lockstring[PATHNAMEFIELD + 1],
  97.                        liststring[7][PATHNAMEFIELD + 1];
  98.  
  99. #define COLUMN_PATHNAME   0
  100. #define COLUMN_DATETIME   1
  101. #define COLUMN_SIZE       2
  102. #define COLUMN_VERSION    3
  103. #define COLUMN_SSDATETIME 4
  104. #define COLUMN_SSSIZE     5
  105. #define COLUMN_SSVERSION  6
  106.  
  107. MODULE struct ColumnInfo ResultColumnInfo[] =
  108. { { 36,            // WORD   ci_Width
  109.     "Pathname",    // STRPTR ci_Title
  110.     0,             // ULONG  ci_Flags
  111.   },
  112.   { 10,
  113.     "Found Date/Time",
  114.     0, /* Last column must not have CIF_DRAGGABLE set (CIF_DRAGGABLE applies
  115.           to the right border of the relevant column). */
  116.   },
  117.   { 7,
  118.     "Found Size",
  119.     0, /* Last column must not have CIF_DRAGGABLE set (CIF_DRAGGABLE applies
  120.           to the right border of the relevant column). */
  121.   },
  122.   { 15,
  123.     "Found Version",
  124.     0, /* Last column must not have CIF_DRAGGABLE set (CIF_DRAGGABLE applies
  125.           to the right border of the relevant column). */
  126.   },
  127.   { 10,
  128.     "Exp. Date/Time",
  129.     0, /* Last column must not have CIF_DRAGGABLE set (CIF_DRAGGABLE applies
  130.           to the right border of the relevant column). */
  131.   },
  132.   { 7,
  133.     "Exp. Size",
  134.     0, /* Last column must not have CIF_DRAGGABLE set (CIF_DRAGGABLE applies
  135.           to the right border of the relevant column). */
  136.   },
  137.   { 15,
  138.     "Expected Version",
  139.     0, /* Last column must not have CIF_DRAGGABLE set (CIF_DRAGGABLE applies
  140.           to the right border of the relevant column). */
  141.   },
  142.   { -1, (STRPTR) ~0, -1
  143. } };
  144.  
  145. MODULE STRPTR ModeOptions[3] =
  146. {   (STRPTR) "Make snapshot of base path",
  147.     (STRPTR) "Compare base path against snapshot",
  148.     NULL
  149. };
  150.  
  151. MODULE struct
  152. {   ULONG red, green, blue, pennumber;
  153. } penn[5] =
  154. {   {0x55555555, 0xFFFFFFFF, 0x55555555, -1}, // green  (OK)        .
  155.     {0xFFFFFFFF, 0x88888888, 0x00000000, -1}, // orange (changed)   !
  156.     {0x55555555, 0xFFFFFFFF, 0xFFFFFFFF, -1}, // cyan   (3rd-party) +
  157.     {0xFFFFFFFF, 0x44444444, 0x44444444, -1}, // red    (missing)   -
  158.     {0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, -1}, // white  (built)    n/a
  159. };
  160.  
  161. // from rp.c
  162. IMPORT SBYTE               page;
  163. IMPORT struct Window*      MainWindowPtr;
  164. IMPORT TEXT                weekdaystring[LEN_DATSTRING],
  165.                            datestring[LEN_DATSTRING],
  166.                            timestring[LEN_DATSTRING];
  167.  
  168. AGLOBAL void files1(void)
  169. {   struct Hook Hook10Struct;
  170.  
  171.     updateghosting();
  172.  
  173.     InitHook(&Hook10Struct, Hook10Func, NULL);
  174.  
  175.     /* Create the window object. */
  176.     lockscreen();
  177.     if (!(WinObject[10] =
  178.     NewObject
  179.     (
  180.     WINDOW_GetClass(), NULL,
  181.     WA_PubScreen,                 ScreenPtr,
  182.     WA_ScreenTitle,               "Report+",
  183.     WA_Title,                     "Report+: System Files Report",
  184.     WA_Activate,                  TRUE,
  185.     WA_DepthGadget,               TRUE,
  186.     WA_DragBar,                   TRUE,
  187.     WA_CloseGadget,               TRUE,
  188.     WA_SizeGadget,                TRUE,
  189.     WA_IDCMP,                     IDCMP_RAWKEY,
  190.     WINDOW_IDCMPHook,             &Hook10Struct,
  191.     WINDOW_IDCMPHookBits,         IDCMP_RAWKEY,
  192.     WINDOW_MenuStrip,             MenuPtr,
  193.     WINDOW_Position,              WPOS_CENTERSCREEN,
  194.     WINDOW_ParentGroup,           files_gadgets[GID_10_LY1] =
  195.                                   NewObject(LAYOUT_GetClass(), NULL,
  196.         // root-layout
  197.         LAYOUT_Orientation,       LAYOUT_ORIENT_VERT,
  198.         LAYOUT_SpaceOuter,        TRUE,
  199.         LAYOUT_DeferLayout,       TRUE,
  200.         LAYOUT_AddChild,          NewObject(LAYOUT_GetClass(), NULL,
  201.             // layout
  202.             LAYOUT_Orientation,   LAYOUT_ORIENT_HORIZ,
  203.             LAYOUT_VertAlignment, LALIGN_CENTER,
  204.             LAYOUT_HorizAlignment,LALIGN_CENTER,
  205.             LAYOUT_BevelStyle,    BVS_NONE,
  206.             LAYOUT_AddChild,
  207.             NewObject
  208.             (   LAYOUT_GetClass(),    NULL,
  209.                 LAYOUT_Orientation,   LAYOUT_ORIENT_VERT,
  210.                 LAYOUT_VertAlignment, LALIGN_CENTER,
  211.                 LAYOUT_HorizAlignment,LALIGN_LEFT,
  212.                 LAYOUT_BevelStyle,    BVS_NONE,
  213.                 LAYOUT_AddChild,
  214.                 NewObject
  215.                 (   LAYOUT_GetClass(),    NULL,
  216.                     LAYOUT_Orientation,   LAYOUT_ORIENT_VERT,
  217.                     LAYOUT_SpaceOuter,    TRUE,
  218.                     LAYOUT_VertAlignment, LALIGN_CENTER,
  219.                     LAYOUT_HorizAlignment,LALIGN_LEFT,
  220.                     LAYOUT_BevelStyle,    BVS_FIELD,
  221.                     LAYOUT_AddImage,
  222.                     NewObject
  223.                     (   LABEL_GetClass(),     NULL,
  224.                         LABEL_Text,           "Show:",
  225.                     TAG_END),
  226.                     CHILD_WeightedHeight,     0,
  227.                     LAYOUT_AddChild,          files_gadgets[GID_10_CB1] =
  228.                     NewObject
  229.                     (   CHECKBOX_GetClass(),  NULL,
  230.                         GA_ID,                GID_10_CB1,
  231.                         GA_RelVerify,         TRUE,
  232.                         CHECKBOX_BackgroundPen, penn[0].pennumber,
  233.                         GA_Text,              "_OK (.)",
  234.                         GA_Selected,          (BOOL) files.show[0],
  235.                     TAG_END),
  236.                     CHILD_WeightedHeight,     0,
  237.                     LAYOUT_AddChild,          files_gadgets[GID_10_CB2] =
  238.                     NewObject
  239.                     (   CHECKBOX_GetClass(),  NULL,
  240.                         GA_ID,                GID_10_CB2,
  241.                         GA_RelVerify,         TRUE,
  242.                         CHECKBOX_BackgroundPen, penn[1].pennumber,
  243.                         GA_Text,              "_Changed (!)",
  244.                         GA_Selected,          (BOOL) files.show[1],
  245.                         TAG_END
  246.                     ),
  247.                     CHILD_WeightedHeight,     0,
  248.                     LAYOUT_AddChild,          files_gadgets[GID_10_CB3] =
  249.                     NewObject
  250.                     (   CHECKBOX_GetClass(),  NULL,
  251.                         GA_ID,                GID_10_CB3,
  252.                         GA_RelVerify,         TRUE,
  253.                         CHECKBOX_BackgroundPen, penn[2].pennumber,
  254.                         GA_Text,              "_3rd-party (+)",
  255.                         GA_Selected,          (BOOL) files.show[2],
  256.                         TAG_END
  257.                     ),
  258.                     CHILD_WeightedHeight,     0,
  259.                     LAYOUT_AddChild,          files_gadgets[GID_10_CB4] =
  260.                     NewObject
  261.                     (   CHECKBOX_GetClass(),  NULL,
  262.                         GA_ID,                GID_10_CB4,
  263.                         GA_RelVerify,         TRUE,
  264.                         CHECKBOX_BackgroundPen, penn[3].pennumber,
  265.                         GA_Text,              "_Missing (-)",
  266.                         GA_Selected,          (BOOL) files.show[3],
  267.                     TAG_END),
  268.                     CHILD_WeightedHeight,     0,
  269.                 TAG_END),
  270.                 CHILD_WeightedHeight,         0,
  271.                 LAYOUT_AddChild,
  272.                 NewObject
  273.                 (   LAYOUT_GetClass(),    NULL,
  274.                     LAYOUT_Orientation,   LAYOUT_ORIENT_VERT,
  275.                     LAYOUT_SpaceOuter,    TRUE,
  276.                     LAYOUT_VertAlignment, LALIGN_CENTER,
  277.                     LAYOUT_HorizAlignment,LALIGN_LEFT,
  278.                     LAYOUT_BevelStyle,    BVS_FIELD,
  279.                     LAYOUT_AddImage,
  280.                     NewObject
  281.                     (   LABEL_GetClass(), NULL,
  282.                         LABEL_Text,       "Compare:",
  283.                     TAG_END),
  284.                     CHILD_WeightedHeight, 0,
  285.                     LAYOUT_AddChild,      files_gadgets[GID_10_CB8] =
  286.                     NewObject
  287.                     (   CHECKBOX_GetClass(), NULL,
  288.                         GA_ID,            GID_10_CB8,
  289.                         GA_RelVerify,     TRUE,
  290.                         GA_Text,          "Si_zes",
  291.                         GA_Selected,      (BOOL) files.checksize,
  292.                         GA_Disabled,      outerghost,
  293.                     TAG_END),
  294.                     CHILD_WeightedWidth,  0,
  295.                     LAYOUT_AddChild,      files_gadgets[GID_10_CB6] =
  296.                     NewObject
  297.                     (   CHECKBOX_GetClass(), NULL,
  298.                         GA_ID,            GID_10_CB6,
  299.                         GA_RelVerify,     TRUE,
  300.                         GA_Text,          "_Dates/times",
  301.                         GA_Selected,      (BOOL) files.checkdatetime,
  302.                         GA_Disabled,      outerghost,
  303.                     TAG_END),
  304.                     CHILD_WeightedWidth,  0,
  305.                     LAYOUT_AddChild,      files_gadgets[GID_10_CB5] =
  306.                     NewObject
  307.                     (   CHECKBOX_GetClass(), NULL,
  308.                         GA_ID,            GID_10_CB5,
  309.                         GA_RelVerify,     TRUE,
  310.                         GA_Text,          "_Versions",
  311.                         GA_Selected,      (BOOL) files.checkversion,
  312.                         GA_Disabled,      outerghost,
  313.                     TAG_END),
  314.                     CHILD_WeightedWidth,  0,
  315.                 TAG_END),
  316.                 CHILD_WeightedHeight,         0,
  317.             TAG_END),
  318.             CHILD_WeightedWidth,      0,
  319.             LAYOUT_AddChild,
  320.             NewObject
  321.             (   LAYOUT_GetClass(),    NULL,
  322.                 LAYOUT_Orientation,   LAYOUT_ORIENT_VERT,
  323.                 LAYOUT_VertAlignment, LALIGN_TOP,
  324.                 LAYOUT_HorizAlignment,LALIGN_CENTER,
  325.                 LAYOUT_BevelStyle,    BVS_NONE,
  326.                 LAYOUT_ShrinkWrap,    TRUE,
  327.                 LAYOUT_AddChild,
  328.                 NewObject
  329.                 (   LAYOUT_GetClass(),    NULL,
  330.                     LAYOUT_Orientation,   LAYOUT_ORIENT_VERT,
  331.                     LAYOUT_SpaceOuter,    TRUE,
  332.                     LAYOUT_VertAlignment, LALIGN_CENTER,
  333.                     LAYOUT_HorizAlignment,LALIGN_CENTER,
  334.                     LAYOUT_BevelStyle,    BVS_FIELD,
  335.                     LAYOUT_AddChild,
  336.                     NewObject
  337.                     (   LAYOUT_GetClass(),    NULL,
  338.                         LAYOUT_Orientation,   LAYOUT_ORIENT_VERT,
  339.                         LAYOUT_SpaceOuter,    TRUE,
  340.                         LAYOUT_VertAlignment, LALIGN_CENTER,
  341.                         LAYOUT_HorizAlignment,LALIGN_CENTER,
  342.                         LAYOUT_BevelStyle,    BVS_FIELD,
  343.                         LAYOUT_ShrinkWrap,    TRUE,
  344.                         LAYOUT_AddChild,
  345.                         NewObject
  346.                         (   LAYOUT_GetClass(),    NULL,
  347.                             LAYOUT_Orientation,   LAYOUT_ORIENT_HORIZ,
  348.                             LAYOUT_SpaceOuter,    TRUE,
  349.                             LAYOUT_VertAlignment, LALIGN_TOP,
  350.                             LAYOUT_HorizAlignment,LALIGN_LEFT,
  351.                             LAYOUT_BevelStyle,    BVS_NONE,
  352.                             LAYOUT_AddImage,
  353.                             NewObject
  354.                             (   LABEL_GetClass(), NULL,
  355.                                 LABEL_Text,       "Mod_e:",
  356.                             TAG_END),
  357.                             CHILD_WeightedWidth,  0,
  358.                         TAG_END),
  359.                         CHILD_WeightedHeight,     0,
  360.                         LAYOUT_AddChild,          files_gadgets[GID_10_RA1] =
  361.                         NewObject
  362.                         (   RADIOBUTTON_GetClass(),NULL,
  363.                             GA_ID,                GID_10_RA1,
  364.                             GA_RelVerify,         TRUE,
  365.                             GA_Text,              ModeOptions,
  366.                             RADIOBUTTON_Selected, (WORD) files.mode,
  367.                         TAG_END),
  368.                     TAG_END),
  369.                     LAYOUT_AddChild,
  370.                     NewObject
  371.                     (   LAYOUT_GetClass(),    NULL,
  372.                         LAYOUT_Orientation,   LAYOUT_ORIENT_HORIZ,
  373.                         LAYOUT_VertAlignment, LALIGN_CENTER,
  374.                         LAYOUT_HorizAlignment,LALIGN_CENTER,
  375.                         LAYOUT_BevelStyle,    BVS_NONE,
  376.                         LAYOUT_ShrinkWrap,    TRUE,
  377.                         LAYOUT_AddImage,
  378.                         NewObject
  379.                         (   LABEL_GetClass(), NULL,
  380.                             LABEL_Text,       "_Snapshot pathname:",
  381.                         TAG_END),
  382.                         CHILD_WeightedWidth,  0,
  383.                         LAYOUT_AddChild,      files_gadgets[GID_10_ST2] =
  384.                         NewObject
  385.                         (   STRING_GetClass(),NULL,
  386.                             GA_ID,            GID_10_ST2,
  387.                             GA_TabCycle,      TRUE,
  388.                             GA_RelVerify,     TRUE,
  389.                             STRINGA_TextVal,  files.snapshot,
  390.                             STRINGA_MaxChars, PATHNAMEFIELD,
  391.                             STRINGA_MinVisible,10,
  392.                         TAG_END),
  393.                         CHILD_WeightedWidth,  100,
  394.                         LAYOUT_AddChild,      files_gadgets[GID_10_BU4] =
  395.                         NewObject
  396.                         (   NULL,             "button.gadget",
  397.                             GA_ID,            GID_10_BU4,
  398.                             GA_RelVerify,     TRUE,
  399.                             BUTTON_AutoButton,BAG_POPFILE,
  400.                         TAG_END),
  401.                         CHILD_WeightedWidth,  0,
  402.                     TAG_END),
  403.                     CHILD_WeightedHeight,     0,
  404.                     LAYOUT_AddChild,
  405.                     NewObject
  406.                     (   LAYOUT_GetClass(),    NULL,
  407.                         LAYOUT_Orientation,   LAYOUT_ORIENT_HORIZ,
  408.                         LAYOUT_VertAlignment, LALIGN_CENTER,
  409.                         LAYOUT_HorizAlignment,LALIGN_CENTER,
  410.                         LAYOUT_BevelStyle,    BVS_NONE,
  411.                         LAYOUT_ShrinkWrap,    TRUE,
  412.                         LAYOUT_AddImage,
  413.                         NewObject
  414.                         (   LABEL_GetClass(), NULL,
  415.                             LABEL_Text,       "_Base path:",
  416.                         TAG_END),
  417.                         CHILD_WeightedWidth,  0,
  418.                         LAYOUT_AddChild,      files_gadgets[GID_10_ST3] =
  419.                         NewObject
  420.                         (   STRING_GetClass(),NULL,
  421.                             GA_ID,            GID_10_ST3,
  422.                             GA_TabCycle,      TRUE,
  423.                             GA_RelVerify,     TRUE,
  424.                             STRINGA_TextVal,  files.basepath,
  425.                             STRINGA_MinVisible,10,
  426.                             STRINGA_MaxChars, PATHNAMEFIELD,
  427.                         TAG_END),
  428.                         CHILD_WeightedWidth,  100,
  429.                         LAYOUT_AddChild,      files_gadgets[GID_10_BU5] =
  430.                         NewObject
  431.                         (   NULL,             "button.gadget",
  432.                             GA_ID,            GID_10_BU5,
  433.                             GA_RelVerify,     TRUE,
  434.                             BUTTON_AutoButton,BAG_POPFILE,
  435.                         TAG_END),
  436.                         CHILD_WeightedWidth,  0,
  437.                     TAG_END),
  438.                     CHILD_WeightedHeight,     0,
  439.                     LAYOUT_AddChild,          files_gadgets[GID_10_FG1] =
  440.                     NewObject
  441.                     (   FUELGAUGE_GetClass(), NULL,
  442.                         GA_ID,                GID_10_FG1,
  443.                         GA_Text,              "Ready.",
  444.                         FUELGAUGE_Level,      0,
  445.                         FUELGAUGE_Percent,    FALSE,
  446.                         FUELGAUGE_Justification,FGJ_CENTER,
  447.                     TAG_END),
  448.                     CHILD_WeightedHeight,     0,
  449.                     LAYOUT_AddChild,
  450.                     NewObject
  451.                     (   LAYOUT_GetClass(),    NULL,
  452.                         LAYOUT_Orientation,   LAYOUT_ORIENT_HORIZ,
  453.                         LAYOUT_VertAlignment, LALIGN_CENTER,
  454.                         LAYOUT_HorizAlignment,LALIGN_CENTER,
  455.                         LAYOUT_BevelStyle,    BVS_NONE,
  456.                         LAYOUT_AddChild,      files_gadgets[GID_10_BU2] =
  457.                         NewObject
  458.                         (   NULL,             "button.gadget",
  459.                             GA_ID,            GID_10_BU2,
  460.                             GA_RelVerify,     TRUE,
  461.                             GA_Text,          "_Update",
  462.                         TAG_END),
  463.                         CHILD_WeightedWidth,  50,
  464.                         LAYOUT_AddChild,      files_gadgets[GID_10_BU3] =
  465.                         NewObject
  466.                         (   NULL,             "button.gadget",
  467.                             GA_ID,            GID_10_BU3,
  468.                             GA_RelVerify,     TRUE,
  469.                             GA_Text,          "Stop",
  470.                             GA_Disabled,      TRUE,
  471.                         TAG_END),
  472.                         CHILD_WeightedWidth,  50,
  473.                     TAG_END),
  474.                     CHILD_WeightedHeight,     0,
  475.                 TAG_END),
  476.                 CHILD_WeightedHeight,         0,
  477.                 LAYOUT_AddChild,
  478.                 NewObject
  479.                 (   LAYOUT_GetClass(),       NULL,
  480.                     LAYOUT_Orientation,      LAYOUT_ORIENT_HORIZ,
  481.                     LAYOUT_VertAlignment,    LALIGN_CENTER,
  482.                     LAYOUT_HorizAlignment,   LALIGN_CENTER,
  483.                     LAYOUT_BevelStyle,       BVS_NONE,
  484.                     LAYOUT_ShrinkWrap,       TRUE,
  485.                     LAYOUT_AddChild,         files_gadgets[GID_10_CB7] =
  486.                     NewObject
  487.                     (   CHECKBOX_GetClass(), NULL,
  488.                         GA_ID,               GID_10_CB7,
  489.                         GA_RelVerify,        TRUE,
  490.                         GA_Text,             "_Log to:",
  491.                         GA_Selected,         (BOOL) files.log,
  492.                         GA_Disabled,         outerghost,
  493.                     TAG_END),
  494.                     CHILD_WeightedWidth,     0,
  495.                     LAYOUT_AddChild,         files_gadgets[GID_10_ST1] =
  496.                     NewObject
  497.                     (   STRING_GetClass(),   NULL,
  498.                         GA_ID,               GID_10_ST1,
  499.                         GA_TabCycle,         TRUE,
  500.                         GA_RelVerify,        TRUE,
  501.                         STRINGA_TextVal,     files.logfile,
  502.                         STRINGA_MinVisible,  10,
  503.                         STRINGA_MaxChars,    PATHNAMEFIELD,
  504.                         GA_Disabled,         innerghost,
  505.                     TAG_END),
  506.                     CHILD_WeightedWidth,     100,
  507.                     LAYOUT_AddChild,      files_gadgets[GID_10_BU1] =
  508.                     NewObject
  509.                     (   NULL,             "button.gadget",
  510.                         GA_ID,            GID_10_BU1,
  511.                         GA_RelVerify,     TRUE,
  512.                         BUTTON_AutoButton,BAG_POPFILE,
  513.                         GA_Disabled,      innerghost,
  514.                     TAG_END),
  515.                     CHILD_WeightedWidth,  0,
  516.                 TAG_END),
  517.                 CHILD_WeightedHeight,     0,
  518.             TAG_END),
  519.             CHILD_WeightedHeight,         0,
  520.         TAG_END),
  521.         CHILD_WeightedHeight,         0,
  522.         LAYOUT_AddChild,              files_gadgets[GID_10_LB1] =
  523.         NewObject
  524.         (   LISTBROWSER_GetClass(),   NULL,
  525.             GA_ID,                    GID_10_LB1,
  526.             GA_ReadOnly,              TRUE,
  527.             GA_TextAttr,              &Topaz8,
  528.             LISTBROWSER_Labels,       (ULONG) &EmptyResultList,
  529.             LISTBROWSER_ColumnInfo,   (ULONG) &ResultColumnInfo,
  530.             LISTBROWSER_ColumnTitles, TRUE,
  531.             LISTBROWSER_HorizontalProp,TRUE,
  532.             LISTBROWSER_VirtualWidth, 620 + 620 + 310,
  533.             LISTBROWSER_MinVisible,   6,
  534.         TAG_END),
  535.         CHILD_WeightedHeight,         100,
  536.         CHILD_MinHeight,              128,
  537.     TAG_END),
  538.     TAG_END
  539.     )))
  540.     {   rq("Can't create ReAction object(s)!");
  541.     }
  542.     unlockscreen();
  543.     openwindow();
  544.     ActivateLayoutGadget(files_gadgets[GID_10_LY1], MainWindowPtr, NULL, (Object) files_gadgets[GID_10_ST2]);
  545.  
  546.     loop();
  547.  
  548.     closewindow();
  549.     files_exit();
  550. }
  551.  
  552. MODULE void updatefiles(void)
  553. {   STRPTR stringptr;
  554.  
  555.     /* Most gadgets are ghosted during the operation. Then their ghosting
  556.     status returns to normal (not necessarily unghosted).
  557.  
  558.         0: Gadget handling.
  559.         1: Set up lists, do the directory examination.
  560.            (For each `source' directory in the `queue', before doing it
  561.            we check for a break. `Break opportunity 1'.)
  562.     At this point we have an empty DirList, and a full FoundList, and an
  563.     empty ResultList.
  564.         2: Create the ResultList.
  565.            (For each `source' file in the `queue', before doing it we
  566.            check for a break. `Break opportunity 2'.)
  567.         3: Show results.
  568.  
  569.        DirList: an Exec list (PathnameNodes) of directories found, awaiting examination.
  570.      FoundList: an Exec list (FilesNodes) of files found, awaiting processing.
  571.   SnapshotList: an Exec list (FilesNodes) of files in the snapshot file.
  572.     ResultList: a listbrowser list of files found, for display.
  573.  
  574.     Apparently the way strings work is that you get told an address where
  575.     the string is stored. This is apparently a pointer into system memory;
  576.     it doesn't need explicit allocation/deallocation by our appliprog. */
  577.  
  578.     if (!(GetAttr
  579.     (   STRINGA_TextVal, files_gadgets[GID_10_ST1], (ULONG *) &stringptr
  580.     )))
  581.     {   rq("Unsupported inquiry!"); // should never happen
  582.     }
  583.     strcpy(files.logfile, stringptr);
  584.  
  585.     if (!(GetAttr
  586.     (   STRINGA_TextVal, files_gadgets[GID_10_ST2], (ULONG *) &stringptr
  587.     )))
  588.     {   rq("Unsupported inquiry!"); // should never happen
  589.     }
  590.     strcpy(files.snapshot, stringptr);
  591.  
  592.     if (!(GetAttr
  593.     (   STRINGA_TextVal, files_gadgets[GID_10_ST3], (ULONG *) &stringptr
  594.     )))
  595.     {   rq("Unsupported inquiry!"); // should never happen
  596.     }
  597.     strcpy(files.basepath, stringptr);
  598.     addslash();
  599.  
  600.     gadgetstate(TRUE);
  601.  
  602.     SetGadgetAttrs
  603.     (   files_gadgets[GID_10_FG1], MainWindowPtr, NULL,
  604.         FUELGAUGE_Min,   0,
  605.         FUELGAUGE_Max,   100,
  606.         FUELGAUGE_Level, 8,
  607.         GA_Text,         "Reading from volume...",
  608.         TAG_END
  609.     ); // we don't know how many files in advance...
  610.  
  611.     SetGadgetAttrs
  612.     (   files_gadgets[GID_10_LB1], MainWindowPtr, NULL,
  613.         LISTBROWSER_Labels, NULL,
  614.         TAG_END
  615.     );
  616.     SetGadgetAttrs
  617.     (   files_gadgets[GID_10_LB1], MainWindowPtr, NULL,
  618.         LISTBROWSER_Labels, (ULONG) &EmptyResultList,
  619.         TAG_END
  620.     );
  621.     if ((ResultList.lh_Head)->ln_Succ) // if the list is non-empty
  622.     {   clearreactionlist(&ResultList);
  623.     }
  624.     filesfound = 0;
  625.  
  626.     status = STATUS_BUSY;
  627.  
  628.     stage1(); // calls stage2() itself if appropriate
  629.  
  630.     status = STATUS_READY;
  631.  
  632.     gadgetstate(FALSE);
  633.     SetGadgetAttrs
  634.     (   files_gadgets[GID_10_FG1], MainWindowPtr, NULL,
  635.         FUELGAUGE_Min,   0,
  636.         FUELGAUGE_Max,   100,
  637.         FUELGAUGE_Level, 0,
  638.         GA_Text,         "Ready.",
  639.         TAG_END
  640.     );
  641.     SetGadgetAttrs
  642.     (   files_gadgets[GID_10_LB1], MainWindowPtr, NULL,
  643.         LISTBROWSER_Labels, NULL,
  644.         TAG_END
  645.     );
  646.  
  647.     if ((ResultList.lh_Head)->ln_Succ) // if the list is non-empty
  648.     {   SetGadgetAttrs
  649.         (   files_gadgets[GID_10_LB1], MainWindowPtr, NULL,
  650.             LISTBROWSER_Labels, (ULONG) &ResultList,
  651.             TAG_END
  652.         );
  653.     } else
  654.     {   SetGadgetAttrs
  655.         (   files_gadgets[GID_10_LB1], MainWindowPtr, NULL,
  656.             LISTBROWSER_Labels, (ULONG) &EmptyResultList,
  657.             TAG_END
  658.         );
  659. }   }
  660.  
  661. MODULE void stage1(void)
  662. {   struct PathnameNode* PathnameNodePtr;
  663.  
  664.     // Initialize lists
  665.     NewList(&FoundList);
  666.     NewList(&DirList);
  667.     NewList(&ResultList);
  668.     NewList(&SnapshotList);
  669.     AddPathnameNode(&DirList, "");
  670.  
  671.     // Pop all the directories from the work stack, and send them one
  672.     // at a time to files_work() for processing.
  673.     while ((DirList.lh_Head)->ln_Succ) // while the list is non-empty
  674.     {   if (ra_checkbreak() == 1) // we don't yet support completely quitting
  675.         {   status = STATUS_STOPPING;
  676.             stopping("Stopping...");
  677.             FreePathnameNodes(&DirList);
  678.             FreeFilesNodes(&FoundList);
  679.             return;
  680.         }
  681.  
  682.         /* detach a node from the DirList, copy its path to activedir,
  683.         free the node, and then call files_work(). */
  684.  
  685.         if (!(PathnameNodePtr = (struct PathnameNode *) RemTail(&DirList)))
  686.         {   rq("RemTail() failed (list is empty!)"); // this should never happen
  687.         }
  688.         strcpy(activedir, PathnameNodePtr->pathname);
  689.         FreeMem(PathnameNodePtr, sizeof(struct PathnameNode));
  690.  
  691.         files_work(); // service routine
  692.     }
  693.  
  694.     /* Now we have a list of all relevant files.
  695.  
  696.     DirList will be empty.
  697.     FoundList will be 'full' (unless the user aborted, or nothing was found).
  698.     ResultList will be empty.
  699.     SnapshotList will be empty. */
  700.  
  701.     stage2();
  702. }
  703.  
  704. MODULE void stage2(void)
  705. {   ABOOL                 matched;
  706.     ULONG                 filesdone = 0,
  707.                           i, j, sizeval,
  708.                           length;
  709.     struct FilesNode     *FoundNodePtr,
  710.                          *SnapshotNodePtr;
  711.     TEXT                  filename[PATHNAMEFIELD + 1],
  712.                           pathname[PATHNAMEFIELD + 1],
  713.                           datetime[18 + 1],
  714.                           version[VLONGFIELD + 1],
  715.                           size[13 + 1];
  716.     struct FileInfoBlock* FIBPtr;
  717.     STRPTR                MemoryPtr;
  718.  
  719. /*  We now have the list of all files found.
  720.  
  721.    *1: Check versions of found files.
  722.     2: Read the snapshot file into memory.
  723.     3: Parse the snapshot file into a list of SnapshotNodes.
  724.     4: Open logfile and write logfile header.
  725.    *5: Check each found node against each snapshot node.
  726.     6: Decide missing files.
  727.  
  728.    * means the operation can be aborted at this point.
  729.  
  730. 1. Check versions of found files. ------------------------------------- */
  731.  
  732.     if (files.mode == FILESMODE_BUILD || files.checkversion)
  733.     {   SetGadgetAttrs
  734.         (   files_gadgets[GID_10_FG1], MainWindowPtr, NULL,
  735.             FUELGAUGE_Min,   0,
  736.             FUELGAUGE_Max,   100,
  737.             FUELGAUGE_Level, 16,
  738.             GA_Text,         "Checking versions...",
  739.             TAG_END
  740.         );
  741.  
  742.         if ((FoundList.lh_Head)->ln_Succ) // if the list is non-empty
  743.         {   for
  744.             (   FoundNodePtr = FoundList.lh_Head;
  745.                 FoundNodePtr->Node.ln_Succ;
  746.                 FoundNodePtr = FoundNodePtr->Node.ln_Succ
  747.             )
  748.             {   if (ra_checkbreak() == 1)
  749.                 {   status = STATUS_STOPPING;
  750.                     stopping("Stopping...");
  751.                     FreeFilesNodes(&FoundList);
  752.                     return;
  753.                 }
  754.                 // check that file is not an icon
  755.                 length = strlen(FoundNodePtr->pathname);
  756.                 if (length < 5 || stricmp(&(FoundNodePtr->pathname[length - 5]), ".info"))
  757.                 {   strcpy(pathname, files.basepath);
  758.                     if (!(AddPart(pathname, FoundNodePtr->pathname, PATHNAMEFIELD)))
  759.                     {   rq("AddPart() failed!");
  760.                     }
  761.                     getversion(pathname, version);
  762.                     if (strlen(version) > VERSIONLENGTH)
  763.                     {   version[VERSIONLENGTH - 3] =
  764.                         version[VERSIONLENGTH - 2] =
  765.                         version[VERSIONLENGTH - 1] = '.';
  766.                         version[VERSIONLENGTH    ] = 0;
  767.                     }
  768.                     strcpy(FoundNodePtr->version, version);
  769.                 } else
  770.                 {   strcpy(FoundNodePtr->version, "n/a");
  771.     }   }   }   }
  772.  
  773. // 2. Read the snapshot file into memory. --------------------------------
  774.  
  775.     if (files.mode == FILESMODE_BUILD)
  776.     {   if (!(TheHandle = (BPTR) Open(files.snapshot, MODE_NEWFILE)))
  777.         {   rq("Can't open snapshot file for writing!");
  778.     }   }
  779.     else
  780.     {   assert(files.mode == FILESMODE_COMPARE);
  781.  
  782.         SetGadgetAttrs
  783.         (   files_gadgets[GID_10_FG1], MainWindowPtr, NULL,
  784.             FUELGAUGE_Min,   0,
  785.             FUELGAUGE_Max,   100,
  786.             FUELGAUGE_Level, 24,
  787.             GA_Text,         "Reading snapshot file...",
  788.             TAG_END
  789.         );
  790.  
  791.         if (!(TheHandle = (BPTR) Lock(files.snapshot, ACCESS_READ)))
  792.         {   rq("Can't lock snapshot file!");
  793.         }
  794.         if (!(FIBPtr    = AllocDosObject(DOS_FIB, NULL)))
  795.         {   UnLock(TheHandle);
  796.             TheHandle = NULL;
  797.             rq("Can't allocate DOS object!");
  798.         }
  799.         if (!(Examine(TheHandle, FIBPtr)))
  800.         {   FreeDosObject(DOS_FIB, FIBPtr);
  801.             FIBPtr = NULL;
  802.             UnLock(TheHandle);
  803.             TheHandle = NULL;
  804.             rq("Can't examine snapshot file!");
  805.         }
  806.         sizeval = FIBPtr->fib_Size;
  807.         comma(sizeval, size);
  808.         stcl_d(size, sizeval);
  809.         FreeDosObject(DOS_FIB, FIBPtr);
  810.         // FIBPtr = NULL;
  811.         UnLock(TheHandle);
  812.         TheHandle = NULL;
  813.  
  814.         // Open the snapshot file, read it into memory, then close it.
  815.         if (!(TheHandle = (BPTR) Open(files.snapshot, MODE_OLDFILE)))
  816.         {   rq("Can't open snapshot file for reading!");
  817.         }
  818.         if (!(MemoryPtr = AllocVec(sizeval, NULL)))
  819.         {   rq("Out of memory!");
  820.         }
  821.         if (Read(TheHandle, MemoryPtr, sizeval) != sizeval)
  822.         {   rq("Can't read from snapshot file!");
  823.         }
  824.         Close(TheHandle);
  825.         TheHandle = NULL;
  826.  
  827. // 3. Parse the snapshot file into a list of SnapshotNodes. --------------
  828.  
  829.         i = 0;
  830.  
  831.         do
  832.         {   j = 0;
  833.             while (*(MemoryPtr + i) != LF)
  834.             {   pathname[j] = *(MemoryPtr + i);
  835.                 i++;
  836.                 j++;
  837.             }
  838.             pathname[j] = 0;
  839.             i++;
  840.  
  841.             j = 0;
  842.             while (*(MemoryPtr + i) != LF)
  843.             {   datetime[j] = *(MemoryPtr + i);
  844.                 i++;
  845.                 j++;
  846.             }
  847.             datetime[j] = 0;
  848.             i++;
  849.  
  850.             j = 0;
  851.             while (*(MemoryPtr + i) != LF)
  852.             {   version[j] = *(MemoryPtr + i);
  853.                 i++;
  854.                 j++;
  855.             }
  856.             version[j] = 0;
  857.             i++;
  858.  
  859.             j = 0;
  860.             while (*(MemoryPtr + i) != LF)
  861.             {   size[j] = *(MemoryPtr + i);
  862.                 i++;
  863.                 j++;
  864.             }
  865.             size[j] = 0;
  866.             i++;
  867.             AddFilesNode(&SnapshotList, pathname, datetime, version, size);
  868.         } while (i < sizeval);
  869.         FreeVec(MemoryPtr);
  870.  
  871. // 4. Open logfile and write logfile header. -----------------------------
  872.  
  873.         if (files.log)
  874.         {   if (!(TheHandle = (BPTR) Open(files.logfile, MODE_READWRITE)))
  875.             {   rq("Can't open logfile for appending!");
  876.             }
  877.             Seek(TheHandle, 0, OFFSET_END);
  878.  
  879.             strcpy(IOBuffer, files.basepath);
  880.             strcat(IOBuffer, " files as at ");
  881.             getdate();
  882.             strcat(IOBuffer, timestring);
  883.             strcat(IOBuffer, " on ");
  884.             strcat(IOBuffer, weekdaystring);
  885.             strcat(IOBuffer, " ");
  886.             strcat(IOBuffer, datestring);
  887.             strcat(IOBuffer, ":\n\n");
  888.             if (Write(TheHandle, IOBuffer, strlen(IOBuffer)) != strlen(IOBuffer))
  889.             {   rq("Can't append to logfile!");
  890.     }   }   }
  891.  
  892. /* 5. Check each found node against each snapshot node. ------------------
  893.  
  894. We go through FoundList destructively, ie. freeing each node after we
  895. have used it.
  896.  
  897. For each file found, we check it against each snapshot node. If it doesn't
  898. match any, it's third-party. */
  899.  
  900.     if (files.mode == FILESMODE_COMPARE)
  901.     {   SetGadgetAttrs
  902.         (   files_gadgets[GID_10_FG1], MainWindowPtr, NULL,
  903.             FUELGAUGE_Min,   0,
  904.             FUELGAUGE_Max,   filesfound * 3,
  905.             FUELGAUGE_Level, filesfound,
  906.             GA_Text,         "Comparing...",
  907.             TAG_END
  908.         );
  909.     } else
  910.     {   assert(files.mode == FILESMODE_BUILD);
  911.         SetGadgetAttrs
  912.         (   files_gadgets[GID_10_FG1], MainWindowPtr, NULL,
  913.             FUELGAUGE_Min,   0,
  914.             FUELGAUGE_Max,   filesfound * 3,
  915.             FUELGAUGE_Level, filesfound,
  916.             GA_Text,         "Writing snapshot file...",
  917.             TAG_END
  918.         );
  919.     }
  920.  
  921.     while ((FoundList.lh_Head)->ln_Succ) // while the list is non-empty
  922.     {   if (ra_checkbreak() == 1)
  923.         {   status = STATUS_STOPPING;
  924.             stopping("Stopping...");
  925.             if (files.mode == FILESMODE_BUILD || files.log)
  926.             {   strcpy(IOBuffer, "Aborted by user!");
  927.                 if (Write(TheHandle, IOBuffer, strlen(IOBuffer)) != strlen(IOBuffer))
  928.                 {   if (files.mode == FILESMODE_COMPARE)
  929.                     {   rq("Can't append to logfile!");
  930.                     } else
  931.                     {   assert(files.mode == FILESMODE_BUILD);
  932.                         rq("Can't write to snapshot file!");
  933.                 }   }
  934.                 Close(TheHandle); // Close() doesn't return an error code
  935.                 TheHandle = NULL;
  936.             }
  937.             FreeFilesNodes(&FoundList);
  938.             FreeFilesNodes(&SnapshotList);
  939.             return;
  940.         }
  941.  
  942.         assert(status != STATUS_STOPPING);
  943.  
  944.         if (!(filesdone % 20))
  945.         {   SetGadgetAttrs
  946.             (   files_gadgets[GID_10_FG1], MainWindowPtr, NULL,
  947.                 FUELGAUGE_Level, filesfound + filesdone,
  948.                 TAG_END
  949.             );
  950.         }
  951.         filesdone++;
  952.  
  953.         if (!(FoundNodePtr = (struct FilesNode *) RemTail(&FoundList)))
  954.         {   rq("RemTail() failed (list is empty!)"); // should never happen
  955.         }
  956.         strcpy(activefile, FoundNodePtr->pathname);
  957.         strcpy(datetime,   FoundNodePtr->datetime);
  958.         strcpy(version,    FoundNodePtr->version );
  959.         strcpy(size,       FoundNodePtr->size    );
  960.         FreeVec(FoundNodePtr);
  961.         // FilesNodePtr = NULL;
  962.  
  963.         strcpy(filename, files.basepath);
  964.         strcat(filename, activefile);
  965.  
  966.         if (files.mode == FILESMODE_BUILD)
  967.         {   strcpy(liststring[COLUMN_PATHNAME], " ");
  968.             strcat(liststring[COLUMN_PATHNAME], activefile);
  969.             strcpy(liststring[COLUMN_DATETIME], datetime);
  970.             strcpy(liststring[COLUMN_SIZE    ], size);
  971.             strcpy(liststring[COLUMN_VERSION ], version);
  972.             strcpy(liststring[COLUMN_SSDATETIME], "n/a");
  973.             strcpy(liststring[COLUMN_SSSIZE   ],  "n/a");
  974.             strcpy(liststring[COLUMN_SSVERSION],  "n/a");
  975.             dobuffer(4);
  976.         } else
  977.         {   // now we have removed the file from the list, and copied its
  978.             // name into activefile. Now we check it against each system
  979.             // file.
  980.             matched = FALSE;
  981.  
  982.             if ((SnapshotList.lh_Head)->ln_Succ) // if the list is non-empty
  983.             {   for
  984.                 (   SnapshotNodePtr = SnapshotList.lh_Head;
  985.                     SnapshotNodePtr->Node.ln_Succ;
  986.                     SnapshotNodePtr = SnapshotNodePtr->Node.ln_Succ
  987.                 )
  988.                 {   if (!matched && !(stricmp(activefile, SnapshotNodePtr->pathname)))
  989.                     {   // we have a match
  990.                         matched = TRUE;
  991.                         SnapshotNodePtr->matched = (ABOOL) TRUE;
  992.         
  993.                         if (files.checkdatetime)
  994.                         {   strcpy(liststring[COLUMN_DATETIME],   datetime);
  995.                             strcpy(liststring[COLUMN_SSDATETIME], SnapshotNodePtr->datetime);
  996.                         } else
  997.                         {   strcpy(liststring[COLUMN_DATETIME],   "n/a");
  998.                             strcpy(liststring[COLUMN_SSDATETIME], "n/a");
  999.                         }                                                                
  1000.         
  1001.                         if (files.checksize)
  1002.                         {   strcpy(liststring[COLUMN_SIZE  ], size);
  1003.                             strcpy(liststring[COLUMN_SSSIZE], SnapshotNodePtr->size);
  1004.                         } else
  1005.                         {   strcpy(liststring[COLUMN_SIZE  ], "n/a");
  1006.                             strcpy(liststring[COLUMN_SSSIZE], "n/a");
  1007.                         }
  1008.  
  1009.                         if (files.checkversion)
  1010.                         {   strcpy(liststring[COLUMN_VERSION],   version);
  1011.                             strcpy(liststring[COLUMN_SSVERSION], SnapshotNodePtr->version);
  1012.                         } else
  1013.                         {   strcpy(liststring[COLUMN_VERSION  ], "n/a");
  1014.                             strcpy(liststring[COLUMN_SSVERSION], "n/a");
  1015.                         }
  1016.                         if
  1017.                         (   (files.checkdatetime && strcmp(SnapshotNodePtr->datetime, liststring[COLUMN_DATETIME]))
  1018.                          || (files.checkversion  && strcmp(SnapshotNodePtr->version,  liststring[COLUMN_VERSION ]))
  1019.                          || (files.checksize     && strcmp(SnapshotNodePtr->size,     liststring[COLUMN_SIZE    ]))
  1020.                         )
  1021.                         {   strcpy(liststring[COLUMN_PATHNAME], "!");
  1022.                             strcat(liststring[COLUMN_PATHNAME], activefile);
  1023.                             if (files.show[1])
  1024.                             {   dobuffer(1);
  1025.                         }   }
  1026.                         else
  1027.                         {   strcpy(liststring[COLUMN_PATHNAME], ".");
  1028.                             strcat(liststring[COLUMN_PATHNAME], activefile);
  1029.                             if (files.show[0])
  1030.                             {   dobuffer(0);
  1031.                         }   }
  1032.                         break;
  1033.             }   }   }
  1034.  
  1035.             if (files.show[2] && !matched) // third-party
  1036.             {   strcpy(liststring[COLUMN_PATHNAME], "+");
  1037.                 strcat(liststring[COLUMN_PATHNAME], activefile);
  1038.  
  1039.                 if (files.checkdatetime)
  1040.                 {   strcpy(liststring[COLUMN_DATETIME], datetime);
  1041.                 } else
  1042.                 {   strcpy(liststring[COLUMN_DATETIME], "?");
  1043.                 }
  1044.                 if (files.checkversion)
  1045.                 {   strcpy(liststring[COLUMN_VERSION], version);
  1046.                 } else
  1047.                 {   strcpy(liststring[COLUMN_VERSION], "?");
  1048.                 }
  1049.                 if (files.checksize)
  1050.                 {   strcpy(liststring[COLUMN_SIZE], size);
  1051.                 } else
  1052.                 {   strcpy(liststring[COLUMN_SIZE], "?");
  1053.                 }
  1054.  
  1055.                 strcpy(liststring[COLUMN_SSDATETIME], "n/a");
  1056.                 strcpy(liststring[COLUMN_SSVERSION ], "n/a");
  1057.                 strcpy(liststring[COLUMN_SSSIZE    ], "n/a");
  1058.                 dobuffer(2);
  1059.     }   }   }
  1060.  
  1061. /* 6. Decide missing files. ----------------------------------------------
  1062.  
  1063. Missing files can't be determined until we have looked through all the
  1064. found files. We go through the snapshot list looking at the `matched'
  1065. member variable. */
  1066.  
  1067.     if (files.mode == FILESMODE_COMPARE)
  1068.     {   // missing files
  1069.  
  1070.         if (status == STATUS_BUSY && files.show[3])
  1071.         {   SetGadgetAttrs
  1072.             (   files_gadgets[GID_10_FG1], MainWindowPtr, NULL,
  1073.                 FUELGAUGE_Min,   0,
  1074.                 FUELGAUGE_Max,   100,
  1075.                 FUELGAUGE_Level, 83,
  1076.                 GA_Text,         "Deciding missing...",
  1077.                 TAG_END
  1078.             );
  1079.  
  1080.             if ((SnapshotList.lh_Head)->ln_Succ) // if the list is non-empty
  1081.             {   for
  1082.                 (   SnapshotNodePtr = SnapshotList.lh_Head;
  1083.                     SnapshotNodePtr->Node.ln_Succ;
  1084.                     SnapshotNodePtr = SnapshotNodePtr->Node.ln_Succ
  1085.                 )
  1086.                 {   if (!(SnapshotNodePtr->matched))
  1087.                     {   strcpy(liststring[COLUMN_PATHNAME], "-");
  1088.                         strcat(liststring[COLUMN_PATHNAME], SnapshotNodePtr->pathname);
  1089.                         strcpy(liststring[COLUMN_VERSION ], "n/a");
  1090.                         strcpy(liststring[COLUMN_DATETIME], "n/a");
  1091.                         strcpy(liststring[COLUMN_SIZE    ], "n/a");
  1092.  
  1093.                         if (files.checkdatetime)
  1094.                         {    strcpy(liststring[COLUMN_SSDATETIME], SnapshotNodePtr->datetime);
  1095.                         } else
  1096.                         {    strcpy(liststring[COLUMN_SSDATETIME], "n/a");
  1097.                         }
  1098.                         if (files.checkversion)
  1099.                         {    strcpy(liststring[COLUMN_SSVERSION], SnapshotNodePtr->version);
  1100.                         } else
  1101.                         {    strcpy(liststring[COLUMN_SSVERSION], "n/a");
  1102.                         }
  1103.                         if (files.checksize)
  1104.                         {    strcpy(liststring[COLUMN_SSSIZE], SnapshotNodePtr->size);
  1105.                         } else
  1106.                         {    strcpy(liststring[COLUMN_SSSIZE], "n/a");
  1107.                         }
  1108.                         dobuffer(3);
  1109.     }   }   }   }   }
  1110.     if (TheHandle)
  1111.     {   Close(TheHandle); // Close() doesn't return an error code
  1112.         TheHandle = NULL;
  1113. }   }
  1114.  
  1115. MODULE void files_work(void)
  1116. {   BOOL                 more;      // BOOL, not ABOOL
  1117.     BPTR                 DirHandle; // = NULL;
  1118.     LONG                 ed;
  1119.     struct ExAllControl* eac;       // = NULL;
  1120.     struct ExAllData*    ead;
  1121.     struct DateTime      DateTime;
  1122.     ULONG                baselength    = strlen(files.basepath);
  1123.     TEXT                 datetime[18 + 1],
  1124.                          size[13 + 1];
  1125.  
  1126.     DateTime.dat_Format  = FORMAT_CDN;
  1127.     DateTime.dat_Flags   = NULL;
  1128.     DateTime.dat_StrDay  = NULL;
  1129.     DateTime.dat_StrDate = datestring;
  1130.     DateTime.dat_StrTime = timestring;
  1131.  
  1132.     /* Service routine for stage1(). Each call of this routine
  1133.     handles one directory from the work stack. This routine is the one
  1134.     that actually makes the DOS calls. It pushes any subdirectories
  1135.     found onto the stack.
  1136.  
  1137.     lockstring contains the pathname of the directory to examine
  1138.         (with base path).
  1139.     activedir contains the pathname of the directory to examine
  1140.         (without base path).
  1141.     activefile will contain the pathname of each file/dir found
  1142.         (with base path). */
  1143.  
  1144.     strcpy(lockstring, files.basepath);
  1145.     strcat(lockstring, activedir);
  1146.  
  1147.     if (!(DirHandle = (BPTR) Lock(lockstring, ACCESS_READ)))
  1148.     {   // Printf("Can't lock %s!\n", lockstring);
  1149.         rq("Can't lock directory!");
  1150.     }
  1151.     if (!(eac = AllocDosObject(DOS_EXALLCONTROL, NULL)))
  1152.     {   UnLock(DirHandle);
  1153.         DirHandle = NULL;
  1154.         rq("Can't allocate DOS object!");
  1155.     }
  1156.  
  1157.     if (files.mode == FILESMODE_BUILD || files.checkdatetime)
  1158.     {   ed = ED_DATE; // we want name, type, size and date
  1159.     } elif (files.checksize)
  1160.     {   ed = ED_SIZE; // we want name, type and size
  1161.     } else
  1162.     {   ed = ED_TYPE; // we want name and type
  1163.     }
  1164.     eac->eac_LastKey = 0;
  1165.     do
  1166.     {   more = ExAll(DirHandle, (struct ExAllData *) EADataPtr, 4096, ed, eac);
  1167.         if (!more && IoErr() != ERROR_NO_MORE_ENTRIES)
  1168.         {   FreeDosObject(DOS_EXALLCONTROL, eac);
  1169.             eac = NULL;
  1170.             UnLock(DirHandle);
  1171.             DirHandle = NULL;
  1172.             rq("Can't examine path!"); /* ExAll() failed abnormally */
  1173.         }
  1174.         if (eac->eac_Entries == 0)
  1175.         {   ; /* ExAll() failed normally with no entries */
  1176.             continue; /* more is USUALLY zero */
  1177.         }
  1178.         ead = (struct ExAllData *) EADataPtr;
  1179.  
  1180.         do
  1181.         {   /* use ead here */
  1182.  
  1183.             strcpy(activefile, lockstring);
  1184.             if (!AddPart(activefile, ead->ed_Name, PATHNAMEFIELD))
  1185.             {   FreeDosObject(DOS_EXALLCONTROL, eac);
  1186.                 eac = NULL;
  1187.                 UnLock(DirHandle);
  1188.                 DirHandle = NULL;
  1189.                 rq("Can't add filename/dirname to path!");
  1190.             }
  1191.             if (ead->ed_Type == 2)
  1192.             // +2 is dir, +3 is softlink (not yet supported), -3 is file
  1193.             {   AddPathnameNode(&DirList, &activefile[baselength]);
  1194.             } elif (ead->ed_Type == -3) // if it's a file
  1195.             {   if (files.mode == FILESMODE_BUILD || files.checkdatetime)
  1196.                 {   DateTime.dat_Stamp.ds_Days   = ead->ed_Days;
  1197.                     DateTime.dat_Stamp.ds_Minute = ead->ed_Mins;
  1198.                     DateTime.dat_Stamp.ds_Tick   = ead->ed_Ticks;
  1199.                     DateToStr(&DateTime);
  1200.                     strcpy(datetime, timestring);
  1201.                     strcat(datetime, " ");
  1202.                     strcat(datetime, datestring);
  1203.                 } else
  1204.                 {   strcpy(datetime, "n/a");
  1205.                 }
  1206.                 if (files.mode == FILESMODE_BUILD || files.checksize)
  1207.                 {   comma(ead->ed_Size, size);
  1208.                 } else
  1209.                 {   strcpy(size, "n/a");
  1210.                 }
  1211.                 AddFilesNode
  1212.                 (   &FoundList,
  1213.                     &activefile[baselength],
  1214.                     datetime,
  1215.                     "",
  1216.                     size
  1217.                 ); 
  1218.  
  1219.                 filesfound++;
  1220.             }
  1221.  
  1222.             /* get next ead */
  1223.             ead = ead->ed_Next;
  1224.         } while(ead);
  1225.     } while(more);
  1226.  
  1227.     FreeDosObject(DOS_EXALLCONTROL, eac);
  1228.     // eac = NULL;
  1229.     UnLock(DirHandle);
  1230.     // DirHandle = NULL;
  1231. }
  1232.  
  1233. MODULE void dobuffer(ULONG whichpen)
  1234. {   struct Node* ListBrowserNodePtr;
  1235.     TEXT         codestring[512 + 1], // codestrings are sometimes longer than 256 chacters
  1236.                  spaces[LONGFIELD + 1];
  1237.     SLONG        gap;
  1238.     ULONG        i;
  1239.  
  1240.     /* Service routine for stage2(). */
  1241.  
  1242.     if (!(ListBrowserNodePtr = AllocListBrowserNode
  1243.     (   7,              // columns,
  1244.         LBNA_Column,    0,
  1245.             LBNA_Flags,     LBFLG_CUSTOMPENS,
  1246.             LBNCA_FGPen,    BLACK,
  1247.             LBNCA_BGPen,    penn[whichpen].pennumber,
  1248.             LBNCA_CopyText, TRUE,
  1249.             LBNCA_Text,     &liststring[0][1],
  1250.         LBNA_Column,    1,
  1251.             LBNA_Flags,     LBFLG_CUSTOMPENS,
  1252.             LBNCA_FGPen,    BLACK,
  1253.             LBNCA_BGPen,    penn[whichpen].pennumber,
  1254.             LBNCA_CopyText, TRUE,
  1255.             LBNCA_Text,     liststring[1],
  1256.         LBNA_Column,    2,
  1257.             LBNA_Flags,     LBFLG_CUSTOMPENS,
  1258.             LBNCA_FGPen,    BLACK,
  1259.             LBNCA_BGPen,    penn[whichpen].pennumber,
  1260.             LBNCA_CopyText, TRUE,
  1261.             LBNCA_Text,     liststring[2],
  1262.         LBNA_Column,    3,
  1263.             LBNA_Flags,     LBFLG_CUSTOMPENS,
  1264.             LBNCA_FGPen,    BLACK,
  1265.             LBNCA_BGPen,    penn[whichpen].pennumber,
  1266.             LBNCA_CopyText, TRUE,
  1267.             LBNCA_Text,     liststring[3],
  1268.         LBNA_Column,    4,
  1269.             LBNA_Flags,     LBFLG_CUSTOMPENS,
  1270.             LBNCA_FGPen,    BLACK,
  1271.             LBNCA_BGPen,    penn[whichpen].pennumber,
  1272.             LBNCA_CopyText, TRUE,
  1273.             LBNCA_Text,     liststring[4],
  1274.         LBNA_Column,    5,
  1275.             LBNA_Flags,     LBFLG_CUSTOMPENS,
  1276.             LBNCA_FGPen,    BLACK,
  1277.             LBNCA_BGPen,    penn[whichpen].pennumber,
  1278.             LBNCA_CopyText, TRUE,
  1279.             LBNCA_Text,     liststring[5],
  1280.         LBNA_Column,    6,
  1281.             LBNA_Flags,     LBFLG_CUSTOMPENS,
  1282.             LBNCA_FGPen,    BLACK,
  1283.             LBNCA_BGPen,    penn[whichpen].pennumber,
  1284.             LBNCA_CopyText, TRUE,
  1285.             LBNCA_Text,     liststring[6],
  1286.     TAG_END)))
  1287.     {   rq("Can't create ReAction listbrowser.gadget node(s)!");
  1288.     }
  1289.     AddTail(&ResultList, ListBrowserNodePtr); // AddTail() has no return code
  1290.  
  1291.     if (files.mode == FILESMODE_BUILD)
  1292.     {   strcpy(codestring, &liststring[COLUMN_PATHNAME][1]);
  1293.         strcat(codestring, "\n");
  1294.         strcat(codestring, liststring[COLUMN_DATETIME]);
  1295.         strcat(codestring, "\n");
  1296.         strcat(codestring, liststring[COLUMN_VERSION]);
  1297.         strcat(codestring, "\n");
  1298.         strcat(codestring, liststring[COLUMN_SIZE   ]);
  1299.         strcat(codestring, "\n");
  1300.  
  1301.         if (Write(TheHandle, codestring, strlen(codestring)) != strlen(codestring))
  1302.         {   rq("Can't write to snapshot file!");
  1303.     }   }
  1304.     else
  1305.     {   assert(files.mode == FILESMODE_COMPARE);
  1306.         if (files.log)
  1307.         {   strcpy(codestring, liststring[COLUMN_PATHNAME]);
  1308.             if (strlen(liststring[COLUMN_PATHNAME]) >= 35)
  1309.             {   strcat(codestring, "\n"
  1310.                 "                                    "); // 36 spaces
  1311.             } else
  1312.             {   gap = 36 - strlen(liststring[COLUMN_PATHNAME]);
  1313.                 for (i = 0; i < gap; i++)
  1314.                 {   spaces[i] = ' ';
  1315.                 }
  1316.                 spaces[gap] = 0;
  1317.                 strcat(codestring, spaces);
  1318.             }
  1319.             if (!(strcmp(liststring[COLUMN_SIZE], "n/a")))
  1320.             {   strcat(codestring, "          n/a "); // 10 spaces
  1321.             } else
  1322.             {   strcat(codestring, liststring[COLUMN_SIZE    ]);
  1323.                 gap = 14 - strlen(liststring[COLUMN_SIZE     ]);
  1324.                 if (gap >= 1)
  1325.                 {   for (i = 0; i < gap; i++)
  1326.                     {   spaces[i] = ' ';
  1327.                     }
  1328.                     spaces[gap] = 0;
  1329.                     strcat(codestring, spaces);
  1330.             }   }
  1331.  
  1332.             strcat(codestring, liststring[COLUMN_DATETIME]);
  1333.             gap = 18 - strlen(liststring[COLUMN_DATETIME]);
  1334.             if (gap >= 1)
  1335.             {   for (i = 0; i < gap; i++)
  1336.                 {   spaces[i] = ' ';
  1337.                 }
  1338.                 spaces[gap] = 0;
  1339.                 strcat(codestring, spaces);
  1340.             }                                    
  1341.             strcat(codestring, liststring[COLUMN_VERSION]);
  1342.             strcat(codestring, "\n"
  1343.             "                                    "); // 36 spaces
  1344.             if (!(strcmp(liststring[COLUMN_SSSIZE], "n/a")))
  1345.             {   strcat(codestring, "          n/a "); // 10 spaces
  1346.             } else
  1347.             {   strcat(codestring, liststring[COLUMN_SSSIZE    ]);
  1348.                 gap = 14 - strlen(liststring[COLUMN_SSSIZE    ]);
  1349.                 if (gap >= 1)
  1350.                 {   for (i = 0; i < gap; i++)
  1351.                     {   spaces[i] = ' ';
  1352.                     }
  1353.                     spaces[gap] = 0;
  1354.                     strcat(codestring, spaces);
  1355.             }   }
  1356.             strcat(codestring, liststring[COLUMN_SSDATETIME]);
  1357.             gap = 18 - strlen(liststring[COLUMN_SSDATETIME]);
  1358.             if (gap >= 1)
  1359.             {   for (i = 0; i < gap; i++)
  1360.                 {   spaces[i] = ' ';
  1361.                 }
  1362.                 spaces[gap] = 0;
  1363.                 strcat(codestring, spaces);
  1364.             }
  1365.             strcat(codestring, liststring[COLUMN_SSVERSION]);
  1366.             strcat(codestring, "\n");
  1367.  
  1368.             if (Write(TheHandle, codestring, strlen(codestring)) != strlen(codestring))
  1369.             {   rq("Can't append to logfile!");
  1370. }   }   }   }
  1371.  
  1372. AGLOBAL void files_init(void)
  1373. {   ULONG        i;
  1374.     struct Node* ListBrowserNodePtr;
  1375.  
  1376.     lockscreen();
  1377.     for (i = 0; i <= 4; i++)
  1378.     {   penn[i].pennumber = FindColor
  1379.         (   ScreenPtr->ViewPort.ColorMap,
  1380.             penn[i].red,
  1381.             penn[i].green,
  1382.             penn[i].blue,
  1383.             -1
  1384.         );
  1385.     }
  1386.     unlockscreen();
  1387.  
  1388.     NewList(&DirList);
  1389.     NewList(&FoundList);
  1390.     NewList(&SnapshotList);
  1391.     NewList(&ResultList);
  1392.     NewList(&EmptyResultList);
  1393.  
  1394.     /* Create a 7-column listbrowser list with only one node containing
  1395.     only column tags. */
  1396.     if (!(ListBrowserNodePtr = AllocListBrowserNode
  1397.     (   7,           // columns
  1398.         /* LBNCA_ tags are those that apply to the specific column. */
  1399.         LBNA_Column, 0,
  1400.         LBNA_Column, 1,
  1401.         LBNA_Column, 2,
  1402.         LBNA_Column, 3,
  1403.         LBNA_Column, 4,
  1404.         LBNA_Column, 5,
  1405.         LBNA_Column, 6,
  1406.         TAG_END
  1407.     )))
  1408.     {   rq("Can't create ReAction listbrowser.gadget node(s)!");
  1409.     }
  1410.     AddTail(&EmptyResultList, ListBrowserNodePtr); // AddTail() has no return code
  1411. }
  1412.  
  1413. AGLOBAL void files_exit(void)
  1414. {   // The window should be closed before calling this.
  1415.     if ((ResultList.lh_Head)->ln_Succ) // if the list is non-empty
  1416.     {   clearreactionlist(&ResultList);
  1417.     }
  1418.     if ((DirList.lh_Head)->ln_Succ) // if the list is non-empty
  1419.     {   FreePathnameNodes(&DirList);
  1420.     }
  1421.     if ((FoundList.lh_Head)->ln_Succ) // if the list is non-empty
  1422.     {   FreeFilesNodes(&FoundList);
  1423.     }
  1424.     if ((SnapshotList.lh_Head)->ln_Succ) // if the list is non-empty
  1425.     {   FreeFilesNodes(&SnapshotList);
  1426.     }
  1427.     if (TheHandle)
  1428.     {   Close(TheHandle); // Close() doesn't return an error code
  1429.         TheHandle = NULL;
  1430.     }
  1431. }
  1432. AGLOBAL void files_die(void)
  1433. {   ULONG i;
  1434.  
  1435.     if ((EmptyResultList.lh_Head)->ln_Succ) // if the list is non-empty
  1436.     {   clearreactionlist(&EmptyResultList);
  1437.     }
  1438.  
  1439.     IOBuffer[23] = (UBYTE) files.log;
  1440.     for (i = 0; i <= 3; i++)
  1441.     {   IOBuffer[i + 8] = (UBYTE) files.show[i];
  1442.     }
  1443.     IOBuffer[7]  = (UBYTE) files.checkversion;
  1444.     IOBuffer[12] = (UBYTE) files.checkdatetime;
  1445.     IOBuffer[13] = (UBYTE) files.mode;
  1446.     IOBuffer[14] = (UBYTE) files.checksize;
  1447. }
  1448.  
  1449. AGLOBAL void files_config(void)
  1450. {   UBYTE i;
  1451.  
  1452.     files.log = (ULONG) IOBuffer[23];
  1453.     for (i = 0; i <= 3; i++)
  1454.     {   files.show[i] = (ULONG) IOBuffer[i + 8];
  1455.     }
  1456.     files.checkversion  = (ULONG) IOBuffer[7];
  1457.     files.checkdatetime = (ULONG) IOBuffer[12];
  1458.     files.mode          = (UWORD) IOBuffer[13];
  1459.     files.checksize     = (ULONG) IOBuffer[14];
  1460. }
  1461.  
  1462. AGLOBAL void files_loop(ULONG gid)
  1463. {   STRPTR stringptr;
  1464.  
  1465.     switch (gid)
  1466.     {
  1467.     case GID_10_RA1:
  1468.         if (!(GetAttr
  1469.         (   RADIOBUTTON_Selected, files_gadgets[GID_10_RA1], (ULONG *) &files.mode
  1470.         )))
  1471.         {   rq("Unsupported inquiry!"); // should never happen
  1472.         }
  1473.         files_updatelog();
  1474.     break;
  1475.     case GID_10_CB1:
  1476.         if (!(GetAttr
  1477.         (   GA_Selected, files_gadgets[GID_10_CB1], (ULONG *) &files.show[0]
  1478.         )))
  1479.         {   rq("Unsupported inquiry!"); // should never happen
  1480.         }
  1481.     break;
  1482.     case GID_10_CB2:
  1483.         if (!(GetAttr
  1484.         (   GA_Selected, files_gadgets[GID_10_CB2], (ULONG *) &(files.show[1])
  1485.         )))
  1486.         {   rq("Unsupported inquiry!"); // should never happen
  1487.         }
  1488.     break;
  1489.     case GID_10_CB3:
  1490.         if (!(GetAttr
  1491.         (   GA_Selected, files_gadgets[GID_10_CB3], (ULONG *) &files.show[2]
  1492.         )))
  1493.         {   rq("Unsupported inquiry!"); // should never happen
  1494.         }
  1495.     break;
  1496.     case GID_10_CB4:
  1497.         if (!(GetAttr
  1498.         (   GA_Selected, files_gadgets[GID_10_CB4], (ULONG *) &files.show[3]
  1499.         )))                                                                    
  1500.         {   rq("Unsupported inquiry!"); // should never happen
  1501.         }
  1502.     break;
  1503.     case GID_10_CB5:
  1504.         if (!(GetAttr
  1505.         (   GA_Selected, files_gadgets[GID_10_CB5], (ULONG *) &files.checkversion
  1506.         )))                                                                    
  1507.         {   rq("Unsupported inquiry!"); // should never happen
  1508.         }
  1509.     break;
  1510.     case GID_10_CB6:
  1511.         if (!(GetAttr
  1512.         (   GA_Selected, files_gadgets[GID_10_CB6], (ULONG *) &files.checkdatetime
  1513.         )))                                                                    
  1514.         {   rq("Unsupported inquiry!"); // should never happen
  1515.         }
  1516.     break;
  1517.     case GID_10_CB7:
  1518.         if (!(GetAttr
  1519.         (   GA_Selected, files_gadgets[GID_10_CB7], &files.log
  1520.         )))
  1521.         {   rq("Unsupported inquiry!"); // should never happen
  1522.         }
  1523.         files_updatelog();
  1524.         if (files.log)
  1525.         {   ActivateLayoutGadget(files_gadgets[GID_10_LY1], MainWindowPtr, NULL, (Object) files_gadgets[GID_10_ST1]);
  1526.         }
  1527.     break;
  1528.     case GID_10_CB8:
  1529.         if (!(GetAttr
  1530.         (   GA_Selected, files_gadgets[GID_10_CB8], (ULONG *) &files.checksize
  1531.         )))
  1532.         {   rq("Unsupported inquiry!"); // should never happen
  1533.         }
  1534.     break;
  1535.     case GID_10_ST1:
  1536.         if (!(GetAttr
  1537.         (   STRINGA_TextVal, files_gadgets[GID_10_ST1], (ULONG *) &stringptr
  1538.         )))
  1539.         {   rq("Unsupported inquiry!"); // should never happen
  1540.         }
  1541.         strcpy(files.logfile, stringptr);
  1542.     break;
  1543.     case GID_10_ST2:
  1544.         if (!(GetAttr
  1545.         (   STRINGA_TextVal, files_gadgets[GID_10_ST2], (ULONG *) &stringptr
  1546.         )))
  1547.         {   rq("Unsupported inquiry!"); // should never happen
  1548.         }
  1549.         strcpy(files.snapshot, stringptr);
  1550.     break;
  1551.     case GID_10_ST3:
  1552.         if (!(GetAttr
  1553.         (   STRINGA_TextVal, files_gadgets[GID_10_ST3], (ULONG *) &stringptr
  1554.         )))
  1555.         {   rq("Unsupported inquiry!"); // should never happen
  1556.         }
  1557.         strcpy(files.basepath, stringptr);
  1558.         addslash();
  1559.     break;
  1560.     case GID_10_BU1:
  1561.         if (asl("#?.log"))
  1562.         {   strcpy(files.logfile, aslresult);
  1563.             SetGadgetAttrs
  1564.             (   files_gadgets[GID_10_ST1], MainWindowPtr, NULL,
  1565.                 STRINGA_TextVal, files.logfile,
  1566.                 TAG_END
  1567.            );
  1568.         }
  1569.     break;
  1570.     case GID_10_BU2:
  1571.         updatefiles();
  1572.     break;
  1573.     case GID_10_BU4:
  1574.         if (asl("#?.snapshot"))
  1575.         {   strcpy(files.snapshot, aslresult);
  1576.             SetGadgetAttrs
  1577.             (   files_gadgets[GID_10_ST2], MainWindowPtr, NULL,
  1578.                 STRINGA_TextVal, files.snapshot,
  1579.                 TAG_END
  1580.             );
  1581.         }
  1582.     break;
  1583.     case GID_10_BU5:
  1584.         if (dirasl())
  1585.         {   strcpy(files.basepath, aslresult);
  1586.             SetGadgetAttrs
  1587.             (   files_gadgets[GID_10_ST3], MainWindowPtr, NULL,
  1588.                 STRINGA_TextVal, files.basepath,
  1589.                 TAG_END
  1590.             );
  1591.             addslash();
  1592.         }
  1593.     break;
  1594.     default:
  1595.     break;
  1596. }   }
  1597.  
  1598. AGLOBAL ULONG Hook10Func(struct Hook *h, VOID *o, VOID *msg)
  1599. {   /* "When the hook is called, the data argument points to the 
  1600.     window object and message argument to the IntuiMessage." */
  1601.  
  1602.     UWORD code, qual;
  1603.     ULONG scroll = 0;
  1604.  
  1605.     geta4(); // wait till here before doing anything
  1606.  
  1607.     code = ((struct IntuiMessage *) msg)->Code;
  1608.     qual = ((struct IntuiMessage *) msg)->Qualifier;
  1609.  
  1610.     switch(code)
  1611.     {
  1612.     case SCAN_HELP:
  1613.         if (status == STATUS_READY)
  1614.         {   helpabout();
  1615.         }
  1616.     break;
  1617.     case SCAN_ESCAPE:
  1618.         if (status == STATUS_READY)
  1619.         {   if ((qual & IEQUALIFIER_LSHIFT) || (qual & IEQUALIFIER_RSHIFT))
  1620.             {   cleanexit(EXIT_SUCCESS);
  1621.             } else page = 0;
  1622.         } else
  1623.         {   assert(status == STATUS_BUSY);
  1624.             status = STATUS_STOPPING;
  1625.         }
  1626.     break;
  1627.     case SCAN_PERIOD:
  1628.         if (asl("#?.log"))
  1629.         {   strcpy(files.logfile, aslresult);
  1630.             SetGadgetAttrs
  1631.             (   files_gadgets[GID_10_ST1], MainWindowPtr, NULL,
  1632.                 STRINGA_TextVal, files.logfile,
  1633.                 TAG_END
  1634.            );
  1635.         }
  1636.     break;
  1637.     case SCAN_E:
  1638.         if (files.mode == 0)
  1639.         {   files.mode = 1;
  1640.         } else
  1641.         {   files.mode = 0;
  1642.         }
  1643.         SetGadgetAttrs
  1644.         (   files_gadgets[GID_10_RA1], MainWindowPtr, NULL,
  1645.             RADIOBUTTON_Selected, files.mode,
  1646.         TAG_END);
  1647.         // we must explicitly refresh
  1648.         RefreshGadgets((struct Gadget *) files_gadgets[GID_10_RA1], MainWindowPtr, NULL);
  1649.         files_updatelog();
  1650.     break;
  1651.     case SCAN_S:
  1652.         ActivateLayoutGadget(files_gadgets[GID_10_LY1], MainWindowPtr, NULL, (Object) files_gadgets[GID_10_ST2]);
  1653.     break;
  1654.     case SCAN_B:
  1655.         ActivateLayoutGadget(files_gadgets[GID_10_LY1], MainWindowPtr, NULL, (Object) files_gadgets[GID_10_ST3]);
  1656.     break;
  1657.     case SCAN_UP:
  1658.         if (qual & IEQUALIFIER_CONTROL)
  1659.         {   scroll = LBP_TOP;
  1660.         } elif (qual & IEQUALIFIER_LSHIFT || qual & IEQUALIFIER_RSHIFT)
  1661.         {   scroll = LBP_PAGEUP;
  1662.         } else scroll = LBP_LINEUP;
  1663.     break;
  1664.     case SCAN_DOWN:
  1665.         if (qual & IEQUALIFIER_CONTROL)
  1666.         {   scroll = LBP_BOTTOM;
  1667.         } elif (qual & IEQUALIFIER_LSHIFT || qual & IEQUALIFIER_RSHIFT)
  1668.         {   scroll = LBP_PAGEDOWN;
  1669.         } else scroll = LBP_LINEDOWN;
  1670.     break;
  1671.     default:
  1672.     break;
  1673.     }
  1674.  
  1675.     if (code == SCAN_UP || code == SCAN_DOWN)
  1676.     {   SetGadgetAttrs
  1677.         (   files_gadgets[GID_10_LB1],    // pointer to gadget
  1678.             MainWindowPtr,                // pointer to window (not window object!)
  1679.             NULL,                         // pointer to requester
  1680.             LISTBROWSER_Position, scroll, // tags
  1681.             TAG_DONE                      // done
  1682.         );
  1683.     }
  1684.  
  1685.     return(1);
  1686. }
  1687.  
  1688. MODULE void stopping(STRPTR status)
  1689. {   SetGadgetAttrs
  1690.     (   files_gadgets[GID_10_FG1], MainWindowPtr, NULL,
  1691.         GA_Text, status,
  1692.         TAG_END
  1693.     );
  1694.     SetGadgetAttrs // `Stop'
  1695.     (   files_gadgets[GID_10_BU3], MainWindowPtr, NULL,
  1696.         GA_Disabled, TRUE,
  1697.         TAG_END
  1698.     );
  1699. }
  1700.  
  1701. MODULE void files_updatelog(void)
  1702. {   ULONG i;
  1703.  
  1704.     updateghosting();
  1705.  
  1706.     SetGadgetAttrs // `Log to file:' (string)
  1707.     (   files_gadgets[GID_10_ST1], MainWindowPtr, NULL,
  1708.         GA_Disabled, innerghost,
  1709.         TAG_END
  1710.     );
  1711.     RefreshGadgets((struct Gadget *) files_gadgets[GID_10_ST1], MainWindowPtr, NULL);
  1712.  
  1713.     SetGadgetAttrs // `Log to file:' (ASL button)
  1714.     (   files_gadgets[GID_10_BU1], MainWindowPtr, NULL,
  1715.         GA_Disabled, innerghost,
  1716.         TAG_END
  1717.     );
  1718.     // buttons can autorefresh
  1719.  
  1720.     SetGadgetAttrs
  1721.     (   files_gadgets[GID_10_CB5], MainWindowPtr, NULL,
  1722.         GA_Disabled, outerghost,
  1723.     TAG_END);
  1724.     RefreshGadgets((struct Gadget *) files_gadgets[GID_10_CB5], MainWindowPtr, NULL);
  1725.  
  1726.     SetGadgetAttrs
  1727.     (   files_gadgets[GID_10_CB6], MainWindowPtr, NULL,
  1728.         GA_Disabled, outerghost,
  1729.     TAG_END);
  1730.     RefreshGadgets((struct Gadget *) files_gadgets[GID_10_CB6], MainWindowPtr, NULL);
  1731.  
  1732.     SetGadgetAttrs
  1733.     (   files_gadgets[GID_10_CB7], MainWindowPtr, NULL,
  1734.         GA_Disabled, outerghost,
  1735.     TAG_END);
  1736.     RefreshGadgets((struct Gadget *) files_gadgets[GID_10_CB7], MainWindowPtr, NULL);
  1737.  
  1738.     SetGadgetAttrs
  1739.     (   files_gadgets[GID_10_CB8], MainWindowPtr, NULL,
  1740.         GA_Disabled, outerghost,
  1741.     TAG_END);
  1742.     RefreshGadgets((struct Gadget *) files_gadgets[GID_10_CB8], MainWindowPtr, NULL);
  1743.  
  1744.     for (i = 0; i <= 3; i++)
  1745.     {   SetGadgetAttrs
  1746.         (   files_gadgets[GID_10_CB1 + i], MainWindowPtr, NULL,
  1747.             GA_Disabled, outerghost,
  1748.         TAG_END);
  1749.         RefreshGadgets((struct Gadget *) files_gadgets[GID_10_CB1 + i], MainWindowPtr, NULL);
  1750. }   }
  1751.  
  1752. MODULE void updateghosting(void)
  1753. {   /* Decides whether certain gadgets should be ghosted or not, and
  1754.     sets variables accordingly. */
  1755.  
  1756.     if (files.mode == FILESMODE_COMPARE)
  1757.     {   outerghost = FALSE;
  1758.         if (files.log)
  1759.         {   innerghost = FALSE;
  1760.         } else
  1761.         {   innerghost = TRUE;
  1762.     }   }
  1763.     else
  1764.     {   assert(files.mode == FILESMODE_BUILD);
  1765.         outerghost =
  1766.         innerghost = TRUE;
  1767. }   }
  1768.  
  1769. MODULE void gadgetstate(ABOOL starting)
  1770. {   /* If starting is TRUE,  we are starting the operation.
  1771.        If starting is FALSE, we are   ending the operation. */
  1772.  
  1773.     BOOL  innerstate, outerstate, inverse;
  1774.     ULONG i;
  1775.  
  1776.     if (starting)
  1777.     {   innerstate =
  1778.         outerstate = starting;
  1779.         inverse    = FALSE;
  1780.     } else
  1781.     {   innerstate = innerghost;
  1782.         outerstate = outerghost;
  1783.         inverse    = TRUE;
  1784.     }
  1785.  
  1786.     // Disabled during operation, enabled otherwise ----------------------
  1787.  
  1788.     SetGadgetAttrs // `Update'
  1789.     (   files_gadgets[GID_10_BU2], MainWindowPtr, NULL,
  1790.         GA_Disabled, starting,
  1791.         TAG_END
  1792.     );
  1793.     // buttons can autorefresh
  1794.  
  1795.     SetGadgetAttrs
  1796.     (   files_gadgets[GID_10_ST2], MainWindowPtr, NULL,
  1797.         GA_Disabled, starting,
  1798.         TAG_END
  1799.     );
  1800.     RefreshGadgets((struct Gadget *) files_gadgets[GID_10_ST2], MainWindowPtr, NULL);
  1801.  
  1802.     SetGadgetAttrs
  1803.     (   files_gadgets[GID_10_ST3], MainWindowPtr, NULL,
  1804.         GA_Disabled, starting,
  1805.         TAG_END
  1806.     );
  1807.     RefreshGadgets((struct Gadget *) files_gadgets[GID_10_ST3], MainWindowPtr, NULL);
  1808.  
  1809.     SetGadgetAttrs
  1810.     (   files_gadgets[GID_10_BU4], MainWindowPtr, NULL,
  1811.         GA_Disabled, starting,
  1812.         TAG_END
  1813.     );
  1814.     // buttons can autorefresh
  1815.  
  1816.     SetGadgetAttrs
  1817.     (   files_gadgets[GID_10_BU5], MainWindowPtr, NULL,
  1818.         GA_Disabled, starting,
  1819.         TAG_END
  1820.     );
  1821.     // buttons can autorefresh
  1822.  
  1823.     /* This should work but seems not to :-(
  1824.     SetGadgetAttrs
  1825.     (   files_gadgets[GID_10_RA1], MainWindowPtr, NULL,
  1826.         GA_Disabled, starting,
  1827.         TAG_END
  1828.     );
  1829.     RefreshGadgets((struct Gadget *) files_gadgets[GID_10_RA1], MainWindowPtr, NULL); */
  1830.  
  1831.     // Enabled during operation, disabled otherwise ----------------------
  1832.  
  1833.     SetGadgetAttrs // `Stop'
  1834.     (   files_gadgets[GID_10_BU3], MainWindowPtr, NULL,
  1835.         GA_Disabled, inverse,
  1836.         TAG_END
  1837.     );
  1838.     // buttons can autorefresh
  1839.  
  1840.     // Disabled during operation and/or in build-mode --------------------
  1841.  
  1842.     for (i = 0; i <= 3; i++)
  1843.     {   SetGadgetAttrs
  1844.         (   files_gadgets[GID_10_CB1 + i], MainWindowPtr, NULL,
  1845.             GA_Disabled, outerstate,
  1846.             TAG_END
  1847.         );
  1848.         RefreshGadgets((struct Gadget *) files_gadgets[GID_10_CB1 + i], MainWindowPtr, NULL);
  1849.     }
  1850.  
  1851.     SetGadgetAttrs
  1852.     (   files_gadgets[GID_10_CB5], MainWindowPtr, NULL,
  1853.         GA_Disabled, outerstate,
  1854.         TAG_END
  1855.     );
  1856.     RefreshGadgets((struct Gadget *) files_gadgets[GID_10_CB5], MainWindowPtr, NULL);
  1857.  
  1858.     SetGadgetAttrs
  1859.     (   files_gadgets[GID_10_CB6], MainWindowPtr, NULL,
  1860.         GA_Disabled, outerstate,
  1861.         TAG_END
  1862.     );
  1863.     RefreshGadgets((struct Gadget *) files_gadgets[GID_10_CB6], MainWindowPtr, NULL);
  1864.  
  1865.     SetGadgetAttrs
  1866.     (   files_gadgets[GID_10_CB7], MainWindowPtr, NULL,
  1867.         GA_Disabled, outerstate,
  1868.         TAG_END
  1869.     );
  1870.     RefreshGadgets((struct Gadget *) files_gadgets[GID_10_CB7], MainWindowPtr, NULL);
  1871.  
  1872.     SetGadgetAttrs
  1873.     (   files_gadgets[GID_10_CB8], MainWindowPtr, NULL,
  1874.         GA_Disabled, outerstate,
  1875.         TAG_END
  1876.     );
  1877.     RefreshGadgets((struct Gadget *) files_gadgets[GID_10_CB8], MainWindowPtr, NULL);
  1878.  
  1879.     // Disabled during operation and/or in build-mode and/or without
  1880.     // logging -----------------------------------------------------------
  1881.  
  1882.     SetGadgetAttrs // `Log to file:' (string)
  1883.     (   files_gadgets[GID_10_ST1], MainWindowPtr, NULL,
  1884.         GA_Disabled, innerstate,
  1885.         TAG_END
  1886.     );
  1887.     RefreshGadgets((struct Gadget *) files_gadgets[GID_10_ST1], MainWindowPtr, NULL);
  1888.  
  1889.     SetGadgetAttrs // `Log to file:' (ASL button)
  1890.     (   files_gadgets[GID_10_BU1], MainWindowPtr, NULL,
  1891.         GA_Disabled, innerstate,
  1892.         TAG_END
  1893.     );
  1894.     // buttons can autorefresh
  1895. }
  1896.  
  1897. MODULE void AddFilesNode(struct List* ListPtr, STRPTR pathname, STRPTR datetime, STRPTR version, STRPTR size)
  1898. {   struct FilesNode* FilesNodePtr;
  1899.     ULONG             needed;
  1900.  
  1901.     needed = sizeof(struct FilesNode) + strlen(pathname);
  1902.  
  1903.     if (!(FilesNodePtr = AllocVec(needed, MEMF_CLEAR | MEMF_PUBLIC)))
  1904.     {   rq("Out of memory!");
  1905.     }
  1906.     strcpy(FilesNodePtr->pathname, pathname);
  1907.     strcpy(FilesNodePtr->datetime, datetime);
  1908.     strcpy(FilesNodePtr->version,  version );
  1909.     strcpy(FilesNodePtr->size,     size    );
  1910.     FilesNodePtr->matched      = FALSE;
  1911.     FilesNodePtr->Node.ln_Name = NULL;
  1912.     FilesNodePtr->Node.ln_Type = NT_USER;
  1913.     FilesNodePtr->Node.ln_Pri  = 0;
  1914.     AddTail((struct List *) ListPtr, (struct Node *) FilesNodePtr);
  1915. }
  1916.  
  1917. MODULE void FreeFilesNodes(struct List* ListPtr)
  1918. {   /* RKM Libraries, p. 496:
  1919.     
  1920.     "Free the entire list, including the header. The header is not
  1921.     updated as the list is freed. This function demonstrates how to
  1922.     avoid referencing freed memory when deallocating nodes." */
  1923.  
  1924.     struct FilesNode *WorkNodePtr, *NextNodePtr;
  1925.     
  1926.     WorkNodePtr = (struct FilesNode *) (ListPtr->lh_Head); /* first node */
  1927.     while (NextNodePtr = (struct FilesNode *) (WorkNodePtr->Node.ln_Succ))
  1928.     {   FreeVec(WorkNodePtr);
  1929.         WorkNodePtr = NextNodePtr;
  1930.     }
  1931.     NewList(ListPtr);
  1932. }
  1933. MODULE void addslash(void)
  1934. {   ULONG length;
  1935.  
  1936.     length = strlen(files.basepath);
  1937.  
  1938.     if (length)
  1939.     {   if
  1940.         (   files.basepath[length - 1] != '/'
  1941.          && files.basepath[length - 1] != ':'
  1942.         )
  1943.         {   strcat(files.basepath, "/");
  1944.             SetGadgetAttrs
  1945.             (   files_gadgets[GID_10_ST3], MainWindowPtr, NULL,
  1946.                 STRINGA_TextVal, files.basepath,
  1947.                 TAG_END
  1948.             );
  1949. }   }   }
  1950.